// there should be a variable amount of uniform sampler2D's here..
// perhaps we should add those using one of those generateHeader functions,
// or append them ourselves to the shader string

// Needed:
// enum for visualization techniques (perhaps represented as integers?)
// enum for blending techniques
// struct to represent the texture grammar

#include "visualizationtechniques.frag"
#include "imageprocessing.frag"
#include "blendingtechniques.frag"

struct TextureGrammar{
    int number_of_fields;
    int visualizationTechniques[32];
    int blendingTechniques[32];
};

uniform vec2 vpdims_;

uniform bool mouseDown_;
uniform vec2 mouseCoord_;

uniform int current_field_;

uniform TextureGrammar texturegrammar;

uniform sampler2D noisemap_;

uniform sampler2D data1_;
uniform sampler2D data2_;
uniform sampler2D data3_;
uniform sampler2D data4_;
uniform sampler2D data5_;
uniform sampler2D data6_;
uniform sampler2D data7_;
uniform sampler2D data8_;
uniform sampler2D data9_;
uniform sampler2D data10_;

// FUNCTION DEFINITIONS: KEEP THIS LIST SYNCHRONIZED WITH MFTGSLICERENDERER.H!
const int MFTG_FIELD_SCALAR = 000,
MFTG_FIELD_VECTOR = 001,

MFTG_VECTOR_LIC = 100,
MFTG_VECTOR_ARROWPLOT = 101,
MFTG_VECTOR_STREAMLINES = 102,

MFTG_SCALAR_COLOURMAP = 200,
MFTG_SCALAR_ISOLINES = 201,

MFTG_PROC_BLUR = 300,
MFTG_PROC_EDGE = 301,

MFTG_COMP_OVERLAY = 400,
MFTG_COMP_BLEND = 401,
MFTG_COMP_BUMPMAP = 402;

// whole bunch of uniforms to determine what methods to use for techniques and blending
uniform int number_of_fields;
uniform int tech1;
uniform int comp1;
uniform int tech2;
uniform int comp2;
uniform int tech3;

// these are not set!!
uniform int comp3;
uniform int tech4;
uniform int comp4;
uniform int tech5;
uniform int comp5;
uniform int tech6;
uniform int comp6;
uniform int tech7;
uniform int comp7;
uniform int tech8;
uniform int comp8;
uniform int tech9;
uniform int comp9;
uniform int tech10;



vec4 applyVisualization(int visualizationid, sampler2D field, vec2 coord){
	vec4 col = vec4(1.0,0.0,0.0,1.0);

	switch(visualizationid)
	{
		case MFTG_SCALAR_COLOURMAP: // FIXME make it so different maps are selected
			col = heatmap( texture(field, clamp(coord/vpdims_, 0.0, 1.0)).x );
			break;
		case MFTG_SCALAR_ISOLINES:
			// has to be in array of 20 long - pad with 0.0
			float isovals[20] = float[20](	0.96, 0.91, 0.85, 0.81, 0.71, 0.61, 0.51, 0.41, 0.31, 0.21,
											0.11, 0.01, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 );
			col = isoline(field, coord, vpdims_, isovals);
			break;
		case MFTG_VECTOR_LIC:
			col = LIC(noisemap_, field, coord, vpdims_, 100);
			break;
		case MFTG_VECTOR_ARROWPLOT:
			col = arrowPlot(field, coord, vpdims_);
			break;
		case MFTG_VECTOR_STREAMLINES:
			col = streamlines(field, coord, vpdims_);
			break;
		default:
			col = vec4(0.0);
			break;
	}

	return col;
}

vec4 applyBlend(int blendid, vec4 c1, vec4 c2){
	vec4 col = vec4(0.0);
	switch(blendid)
	{
		case MFTG_COMP_BLEND:
			col = blend(c1, c2, 0.7);
			break;
		case MFTG_COMP_OVERLAY:
			col = overlay(c1, c2, 0.3);
			break;
		case MFTG_COMP_BUMPMAP:
			// TODO come up with something to make this possible,
			// we need the actual sampler2D for calculating the bumpmap
		default:
			col = blend(c1, c2, 0.7);
			break;

	}
	return col;
}

vec4 imageProcessing(sampler2D image){
	return vec4(0.0);
}

/***************************************************************
 * Some stuff to simulate a lens and enlarge part of the image *
 ***************************************************************/
float LENS_SIZE = min(vpdims_.x, vpdims_.y) / 4;
float SCALE_FACTOR = 1.00;
float ENLARGED_SIZE = LENS_SIZE * SCALE_FACTOR;
float RIDGE_SIZE = LENS_SIZE * 0.04;
vec4 RIDGE_COLOUR = vec4(0.3, 0.9, 0.6, 1.0);

vec4 get_ridge_colour(float distn){
	float midridge = RIDGE_SIZE * 0.5;
	float distridge = LENS_SIZE - distn;
	float midridgedist = 1.0 - (abs(midridge - distridge) / midridge);
	return RIDGE_COLOUR * midridgedist;
}

void main(){
    // stores the accumulated pixel colour
    vec4 col = vec4(0.0);

    vec2 fragcoord = gl_FragCoord.xy;
	col = vec4(0.0);

	vec4 col1 = vec4(0.0);
	vec4 col2 = vec4(0.0);
	vec4 col3 = vec4(0.0);
	vec4 col4 = vec4(0.0);
	vec4 col5 = vec4(0.0);
	vec4 col6 = vec4(0.0);
	vec4 col7 = vec4(0.0);
	vec4 col8 = vec4(0.0);
	vec4 col9 = vec4(0.0);
	vec4 col10 = vec4(0.0);


	// lens functionality
	vec2 middle = vec2(mouseCoord_.x, mouseCoord_.y);
	vec2 ptm = middle - fragcoord;
	float dist = sqrt( ptm.x*ptm.x + ptm.y*ptm.y );
	if(dist < LENS_SIZE && mouseDown_){
		if(dist >= LENS_SIZE - RIDGE_SIZE){ col = get_ridge_colour(dist); }
		else{
			// scale the vector pointing to the middle of the lens to match the enlarged area
			// proportions, and translate from the lens centre to obtain coordinates in enlarged area
			ptm *= SCALE_FACTOR;
			vec2 lensCoord = middle - ptm;
			fragcoord = lensCoord;

			switch(current_field_){
			case 1:
				col = applyVisualization(tech1, data1_, fragcoord);
				break;
			case 2:
				col = applyVisualization(tech2, data2_, fragcoord);
				break;
			case 3:
				col = applyVisualization(tech3, data3_, fragcoord);
				break;
			case 4:
				col = applyVisualization(MFTG_SCALAR_ISOLINES, data4_, fragcoord);
				break;
			default:
				col = applyVisualization(tech1, data1_, fragcoord);
				break;
			}

			//if(dist < (LENS_SIZE*0.03)){ col = vec4(1.0,0.0,0.0,1.0); }
		}
	}else{

// MFTG_COMP_BUMPMAP is an exception and is handled differently

		if(number_of_fields >= 1){
			col1 = applyVisualization(tech1, data1_, fragcoord);
			col = col1;
		}
		if(number_of_fields >= 2){
			if(comp1 == MFTG_COMP_BUMPMAP){ col = bumpmap(col, data2_, fragcoord, vpdims_, vec2(-1, -1)); }
			else{
				col2 = applyVisualization(tech2, data2_, fragcoord);
				col = applyBlend(comp1, col2, col);
			}
		}
		if(number_of_fields >= 3){
			if(comp2 == MFTG_COMP_BUMPMAP){ col = bumpmap(col, data3_, fragcoord, vpdims_, vec2(-1, -1)); }
			else{
				col3 = applyVisualization(tech3, data3_, fragcoord);
				col = applyBlend(comp2, col3, col);
			}
		}
		/*
		if(number_of_fields >= 4){
			if(comp3 == MFTG_COMP_BUMPMAP){ col = bumpmap(col, data4_, fragcoord, vpdims_, vec2(-1, -1)); }
			else{
				col4 = applyVisualization(tech4, data4_, fragcoord);
				col = applyBlend(comp3, col4, col);
			}
		}
		if(number_of_fields >= 5){
			if(comp4 == MFTG_COMP_BUMPMAP){ col = bumpmap(col, data5_, fragcoord, vpdims_, vec2(-1, -1)); }
			else{
				col5 = applyVisualization(tech5, data5_, fragcoord);
				col = applyBlend(comp4, col, col5);
			}
		}
		if(number_of_fields >= 6){
			if(comp5 == MFTG_COMP_BUMPMAP){ col = bumpmap(col, data6_, fragcoord, vpdims_, vec2(-1, -1)); }
			else{
				col6 = applyVisualization(tech6, data6_, fragcoord);
				col = applyBlend(comp5, col, col6);
			}
		}
		if(number_of_fields >= 7){
			if(comp6 == MFTG_COMP_BUMPMAP){ col = bumpmap(col, data7_, fragcoord, vpdims_, vec2(-1, -1)); }
			else{
				col7 = applyVisualization(tech7, data7_, fragcoord);
				col = applyBlend(comp6, col, col7);
			}
		}
		if(number_of_fields >= 8){
			if(comp7 == MFTG_COMP_BUMPMAP){ col = bumpmap(col, data8_, fragcoord, vpdims_, vec2(-1, -1)); }
			else{
				col8 = applyVisualization(tech8, data8_, fragcoord);
				col = applyBlend(comp7, col, col8);
			}
		}
		if(number_of_fields >= 9){
			if(comp8 == MFTG_COMP_BUMPMAP){ col = bumpmap(col, data9_, fragcoord, vpdims_, vec2(-1, -1)); }
			else{
				col9 = applyVisualization(tech9, data9_, fragcoord);
				col = applyBlend(comp8, col, col9);
			}
		}
		if(number_of_fields >= 10){
			if(comp9 == MFTG_COMP_BUMPMAP){ col = bumpmap(col, data10_, fragcoord, vpdims_, vec2(-1, -1)); }
			else{
				col10 = applyVisualization(tech10, data10_, fragcoord);
				col = applyBlend(comp9, col, col10);
			}
		}
		*/
		//col = vec4(1.0,0.0,0.0,1.0);
	}

    FragData0 = col;
}
